Spring 5.0.0框架介绍_中文版_3.2

文章作者:Tyan
博客:noahsnail.com

3.2 容器概述

`org.springframework.context.ApplicationContext`接口代表了Spring IoC容器并且负责实例化、配置和组装前面提到的beans。容器通过读取配置元数据得到说明什么对象要实例化、配置和组装。配置元数据可以用XML、Java注解或Java代码表示。它允许你表示构成应用的对象和对象间丰富的依赖关系。

Spring提供了一些可以直接使用的`ApplicationContext`接口实现。在单独的应用中通常是创建一个 `ClassPathXmlApplicationContext`实例或`FileSystemXmlApplicationContext`实例。虽然XML是定义配置元数据的传统格式,但你可以指示容器支持使用Java注解或代码作为元数据的格式并通过提供少量的XML配置声明使容器支持这些额外的元数据格式。

在大多数应用场景中,不会要求用户用显式的代码来实例化一个或多个Spring IoC容器的。例如,在web应用场景中,在应用的`web.xml`文件中写一个简单的八行左右的样板web描述符XML就足够了(看3.13.4小节,『web应用中ApplicationContext的方便实例化』)。如果你正在使用Eclipse支持的Spring Tool Suite开发环境,可以很容易的通过点几下鼠标或键盘来创建样本配置。

下面的图是从一个高层次的视野来看Spring是如何工作的。你的应用类与配置元数据结合起来为的是在`ApplicationContext`创建和初始化之后,你有一个完整配置并可执行的系统或应用。

图3.1. Spring IoC容器
image

3.2.1 配置元数据

如上图所示,Spring IoC容器使用了一种*配置元数据*的方式;配置元数据表示你作为一个应用开发者应该告诉Spring容器怎样去实例化、配置并组装应用中的对象。

习惯上用简单直观下XML形式来提供配置元数据,这一章大部分使用XML文件来表达Spring IoC容器的核心概念及功能。

基于XML的元数据不是配置元数据的唯一许可形式。Spring IoC容器本身与配置元数据的实际书写形式是完全解构的。目前许多开发者在他们的Spring应用中选用基于Java配置的元数据形式。

关于Spring容器中使用其它元数据形式的信息,请看:
  • 基于注解的配置:Spring 2.5引入对了基于注解的配置元数据的支持。
  • 基于Java的配置:从Spring 3.0开始,Spring JavaConfig工程提供的许多功能开始成为Spring框架核心中的一部分。因此你可以通过Java而不是XML文件来定义外部应用程序的beans。为了使用这些新功能,请看@Configuration, @Bean, @Import@DependsOn注解。

    Spring配置包括至少一个且通常不止一个容器必须管理的bean定义。基于XML的配置元数据中,这些beans作为`<bean>`元素被配置在顶层`<beans/>`元素中。Java配置通常在`@Configuration`类中使用`@Bean`注解的方法。
    
    这些bean定义与组成你应用的实际对象相对应。通常你会定义服务层对象,数据访问层对象(DAOs),描述对象例如Struts的`Action`实例,底层对象例如Hibernate的`SessionFactories`,JMS的`Queues`等等。容器中细粒度的领域对象通常是不配置的,因为一般是由DAOs和业务逻辑负责创建和加载领域对象。然而你可以使用Spring集成的AspectJ去配置IoC容器控制之外创建的对象。请看"使用Spring的AspectJ来依赖注入领域对象"。
    
    下面的例子展示了基于XML配置元数据的基本结构:
    
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">

<bean id="..." class="...">
<!-- collaborators and configuration for this bean go here -->
</bean>

<bean id="..." class="...">
<!-- collaborators and configuration for this bean go here -->
</bean>

<!-- more bean definitions go here -->

</beans>
`id`属性是一个你用来识别私有bean定义的字符串。`class`属性定义了bean的类型并且使用了完全限定类型名称(全限定名称或完全限定名)。`id`属性的值引用了协作对象。这个例子的中没有展示如何引用协作对象,更多信息请查看『依赖』。

3.2.2 实例化容器

实例化一个Spring IoC容器是简单的。一个或多个提供给`ApplicationContext`构造函数的定位路径实际上是资源字符串,可以让容器从各种例如局部文件系统,Java的`CLASSPATH`等外部资源中加载配置元数据。
1
2
ApplicationContext context =
new ClassPathXmlApplicationContext(new String[] {"services.xml", "daos.xml"});

在你学习Spring IoC容器之后,你可能想知道更多关于Spring的Resource抽象信息,像『第四章 资源』描述的那样,Resource抽象提供了一种从URI语法定义的位置中读取输入流的方便机制。Resource路径通常被用来构建应用程序上下文,正如4.7 小节『应用上下文和资源路径』描述的那样。

下面的例子是服务层对象(`services.xml`)的配置文件:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">

<!-- services -->

<bean id="petStore" class="org.springframework.samples.jpetstore.services.PetStoreServiceImpl">
<property name="accountDao" ref="accountDao"/>
<property name="itemDao" ref="itemDao"/>
<!-- additional collaborators and configuration for this bean go here -->
</bean>

<!-- more bean definitions for services go here -->

</beans>
下面的例子是数据访问对象`daos.xml`的配置文件:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">

<bean id="accountDao"
class="org.springframework.samples.jpetstore.dao.jpa.JpaAccountDao">
<!-- additional collaborators and configuration for this bean go here -->
</bean>

<bean id="itemDao" class="org.springframework.samples.jpetstore.dao.jpa.JpaItemDao">
<!-- additional collaborators and configuration for this bean go here -->
</bean>

<!-- more bean definitions for data access objects go here -->

</beans>
在之前的例子中,服务层包括类`PetStoreServiceImpl`和两个类型为`JpaAccountDao`和`JpaItemDao`数据访问对象(基于JPA对象/关系映射标准)。`property name`元素指的是JavaBean属性的名称,`ref`元素指的是另一个bean定义的名称。`id`和`ref`之间的连接表明了协作对象之间的关系。配置对象依赖的更详细信息请看『依赖』。

创建基于XML的元数据

bean定义跨越多个XML文件是非常有用的。通常每一个独立的XML配置文件表示你架构中的一个逻辑层或模块。

在上面的例子中,外部bean定义从`services.xml`、`messageSource.xml`和`themeSource.xml`三个文件中加载。所有位置路径都是相对于进行导入的定义文件的,因此`services.xml`必须跟进行导入的文件在同一个目录下或同一个classpath位置下。如你所见,忽略了最前面的反斜杠,但给定的这些路径是相对的,最好是一点都不使用反斜杠。包括顶层的`<beans/>`元素在内,被导入的文件内容必须是依据Spring Schema有效的XML bean定义。

在父目录的引用文件使用”../“相对路径是可以的,但不推荐这样做。这样做会产生一个当前应用之外文件依赖。引用文件特别不推荐在”classpath:” URLs中(例如”classpath:../services.xml”),运行时解析处理会选择”最近的”classpath根目录,然后去寻找它的父目录。Classpath配置的更改可能会导致进入一个不同且不正确的目录。

你可以总是使用完全限定资源位置代替相对路径:例如,”file:C:/config/services.xml”或”classpath:/config/services.xml”。但是要注意你正在将你的应用配置与特定的绝对路径耦合。通常更可取的方式是间接的访问绝对路径,例如,通过”${…​}”占位符在运行时解析JVM系统属性。

3.2.3 使用容器

`ApplicationContext`是一个更高级的工厂接口,它能维护不同beans及其依赖的注册表。使用方法`T getBean(String name, Class<T> requiredType)`你可以取回你的beans实例。

`ApplicationContext`能让你用下面的方式读取bean定义及访问它们:
1
2
3
4
5
6
7
8
9
// create and configure beans
ApplicationContext context =
new ClassPathXmlApplicationContext(new String[] {"services.xml", "daos.xml"});

// retrieve configured instance
PetStoreService service = context.getBean("petStore", PetStoreService.class);

// use configured instance
List<String> userList = service.getUsernameList();
你可以用`getBean()`取回你的beans实例。`ApplicationContext`接口有一些其它的方法来取回beans,但理想的应用代码应该绝不使用它们。事实上,你的应用代码应该完全不调用`getBean()`方法,因此完全不依赖Spring APIs。例如,Spring的集成web框架提供了各种web框架类的依赖注入,例如控制器和JSF管理的beans。
如果有收获,可以请我喝杯咖啡!